package com.zondy.mapgis.android.frag;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PointF;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;

import com.baidu.location.BDLocation;
import com.baidu.location.LocationClientOption;
import com.zondy.mapgis.android.activity.MapActivity;
import com.zondy.mapgis.android.activity.MyTracksActivity;
import com.zondy.mapgis.android.base.BaseFragment;
import com.zondy.mapgis.android.gpx.GPXParser;
import com.zondy.mapgis.android.gpx.bean.GPX;
import com.zondy.mapgis.android.gpx.bean.Track;
import com.zondy.mapgis.android.gpx.bean.Waypoint;
import com.zondy.mapgis.android.graphic.GraphicImage;
import com.zondy.mapgis.android.graphic.GraphicMultiPoint;
import com.zondy.mapgis.android.graphic.GraphicPolylin;
import com.zondy.mapgis.android.mapview.MapView;
import com.zondy.mapgis.android.mapview.MapView.MapViewScreenSnapshotCallback;
import com.zondy.mapgis.android.model.EnumViewPos;
import com.zondy.mapgis.android.service.LocationService;
import com.zondy.mapgis.android.service.MyLocationListener;
import com.zondy.mapgis.android.utils.BitmapUtils;
import com.zondy.mapgis.android.utils.DialogUtil;
import com.zondy.mapgis.android.utils.MapUtil;
import com.zondy.mapgis.android.utils.PointTransferUtil;
import com.zondy.mapgis.android.utils.PopupWindowUtil;
import com.zondy.mapgis.android.utils.PopupWindowUtil.PopupWindowConfirmListener;
import com.zondy.mapgis.android.utils.ToolToast;
import com.zondy.mapgis.android.utils.ValueUtil;
import com.zondy.mapgis.core.geometry.Dot;
import com.zondy.mapgis.explorer.MapApplication;
import com.zondy.mapgis.explorer.R;
import com.zondy.mapgis.map.model.ConfigManager;
import com.zondy.mapgis.map.model.Counter;
import com.zondy.mapgis.track.GNNSInfo;

/**
 * 轨迹记录模块
 * 
 * @author fjl
 * 
 */
public class RecordTracksFrag extends BaseFragment implements OnClickListener
{
	private String TAG = this.getClass().getSimpleName();
	private String TRACKS_PATH = MapApplication.SystemLibraryPath + "Tracks";
	private MapActivity mMapActivity = null;
	private MapView mMapView = null;
	private GraphicMultiPoint mGraphicMultiPoint = null;
	private GraphicPolylin mGraphicPolylin = null;
	private GraphicImage mGraphicImage = new GraphicImage();

	private TextView mTitleTxt = null;
	private ImageView mTrackSetting = null;
	private LinearLayout mContent = null;
	private LinearLayout mRunInfoLayout = null;
	private ImageView mStartImv = null;
	private ImageView mStopImv = null;
	private ImageView mFinishImv = null;
	private TextView mRouteLength = null;
	private Chronometer mTimeCm = null;
	private boolean mIsPause = false;

	public MyLocationListener mMyLocationListener = null;
	private LocationService locationService;
	private LocationClientOption mOption = null;
	private ConfigManager mTracksConfig = null;
	private Track mTrack = new Track();
	private com.zondy.mapgis.track.Track mMapgisTrack;
	private ArrayList<Waypoint> mWayPoints = null;
	private Dot mStartDot = new Dot();
	private Dot mEndDot = new Dot();
	private boolean IsStartDot = true;
	private String mStartName = null;
	private String mTrackDis = "0.0km";
	private Bitmap mStartBmp;
	private Counter mCounter = new Counter(0);
	private long mStartlongTime = 0;
	private long mEndlongTime = 0;
	private String mCurrentTime = "2016";

	private WakeLock wakeLock = null;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		Log.d(TAG, "BaseFragment-->onCreate()");
		if (savedInstanceState != null)
		{
			// 后台自动销毁，保存的数据
			mWayPoints = (ArrayList<Waypoint>) savedInstanceState.get("mWayPoints");
			Log.e(TAG, "savedInstanceState != null");
			Log.e(TAG, "" + mWayPoints.get(0).getLongitude());
			Log.e(TAG, "" + mWayPoints.get(0).getLatitude());
			// startRun();
		}
	}

	@Override
	public int bindLayout()
	{
		return R.layout.record_tracks_frag;
	}

	@Override
	public void onStart()
	{
		acquireWakeLock();
		super.onStart();
	}

	@Override
	public void initView(View view)
	{
		mTitleTxt = (TextView) view.findViewById(R.id.title_text);
		mTrackSetting = (ImageView) view.findViewById(R.id.more_btn);
		mTitleTxt.setText("记录轨迹");
		mTrackSetting.setVisibility(View.VISIBLE);
		mContent = (LinearLayout) view.findViewById(R.id.record_content_layout);
		mRunInfoLayout = (LinearLayout) view.findViewById(R.id.runinfo_layout);
		mStartImv = (ImageView) view.findViewById(R.id.start_sport_iv);
		mStopImv = (ImageView) view.findViewById(R.id.stop_sport_iv);
		mFinishImv = (ImageView) view.findViewById(R.id.finish_sport_iv);
		mRouteLength = (TextView) view.findViewById(R.id.route_length_tv);
		mTimeCm = (Chronometer) view.findViewById(R.id.time_cm);

		view.findViewById(R.id.title_back).setOnClickListener(this);
		mTrackSetting.setOnClickListener(this);
		mStartImv.setOnClickListener(this);
		mStopImv.setOnClickListener(this);
		mFinishImv.setOnClickListener(this);

		mStartBmp = BitmapFactory.decodeResource(getResources(), R.drawable.bubble_start);
	}

	@Override
	public void doBusiness(Context mContext)
	{
		mMapActivity = MapApplication.getApp().getMapActivity();
		mTracksConfig = ConfigManager.getInstance(getContext());
		mMapActivity.mMapBottomContent.setVisibility(View.GONE);
		mMapActivity.mMapRightContent.setVisibility(View.GONE);
		mMapActivity.mComposerButtonsWrapper.setVisibility(View.GONE);
		mMapActivity.mZoomLayout.setVisibility(View.GONE);
		mMapView = mMapActivity.mMapView;
		if (mGraphicMultiPoint == null)
		{
			mGraphicMultiPoint = new GraphicMultiPoint();
			mGraphicMultiPoint.setColor(Color.RED);
			mGraphicMultiPoint.setPointSize(12.0);
		}
		if (mGraphicPolylin == null)
		{
			mGraphicPolylin = new GraphicPolylin();
			mGraphicPolylin.setColor(Color.GREEN);
			mGraphicPolylin.setLineWidth(6.0f);
		}
		mMapView.getGraphicsOverlay().addGraphic(mGraphicMultiPoint);
		mMapView.getGraphicsOverlay().addGraphic(mGraphicPolylin);

//		// 初始化定位
//		initLocation();

		mWayPoints = new ArrayList<Waypoint>();
		//MapGIS Mobile采集轨迹类
		mMapgisTrack = new com.zondy.mapgis.track.Track();
	}

	/**
	 * 初始化定位信息
	 */
	public void initLocation()
	{
		// 获取locationservice实例，建议应用中只初始化1个location实例，然后使用，可以参考其他示例的activity，都是通过此种方式获取locationservice实例的
		locationService = MapApplication.getApp().locationService;
		// 设置定位监听
		mMyLocationListener = new MyLocationListener(locHander);
		locationService.registerListener(mMyLocationListener);
		// 设置定位参数
		mOption = locationService.getDefaultLocationClientOption();
		if (MapApplication.getApp().isIsRecodSetting())
		{
			mOption = locationService.getOption();
		}
		else
		{
			mOption = locationService.getRecordLocationClientOption();
		}
		locationService.setLocationOption(mOption);
	}

	/***
	 * 接收定位结果消息，并显示在地图上
	 */
	private Handler locHander = new Handler()
	{
		@Override
		public void handleMessage(Message msg)
		{
			super.handleMessage(msg);
			BDLocation location = msg.getData().getParcelable("loc");
			// log test
			if (null != location && location.getLocType() != BDLocation.TypeServerError)
			{
				mTrack.setName(mStartName + "-" + location.getLocationDescribe());
			}
			// GPS定位
			if (location.getLocType() == BDLocation.TypeGpsLocation)
			{
				Waypoint waypoint = new Waypoint();
				if (IsStartDot)
				{
					mStartName = location.getCity() + location.getStreet() + location.getDistrict();
					mStartDot.x = location.getLongitude();
					mStartDot.y = location.getLatitude();
					addGraphicImg(mStartBmp, PointTransferUtil.Lonlat2Mercator(mStartDot));
					IsStartDot = false;
				}
				waypoint.setLatitude(location.getLatitude());
				waypoint.setLongitude(location.getLongitude());
				mWayPoints.add(waypoint);
				
				//MapGIS track
				Dot lonlat = new Dot(location.getLongitude(), location.getLatitude());
				GNNSInfo gpsInfo = new GNNSInfo();
				gpsInfo.setlongitude(lonlat.x);
				gpsInfo.setlatitude(lonlat.y);
				mMapgisTrack.addLocation(gpsInfo);

				mEndDot.x = location.getLongitude();
				mEndDot.y = location.getLatitude();
				mTrackDis = getRouteDis(mStartDot, mEndDot);
				mRouteLength.setText(mTrackDis);
			}
			else if (location.getLocType() == BDLocation.TypeNetWorkLocation)
			{
				if (IsStartDot)
				{
					mStartName = location.getLocationDescribe();
					mStartDot.x = location.getLongitude();
					mStartDot.y = location.getLatitude();
					addGraphicImg(mStartBmp, PointTransferUtil.Lonlat2Mercator(mStartDot));

					Waypoint startPoint = new Waypoint();
					startPoint.setLatitude(mStartDot.y);
					startPoint.setLongitude(mStartDot.x);
					mWayPoints.add(startPoint);
					mCounter.increase();
					IsStartDot = false;
				}
				// 室内测试
//				 mTrack.setName(mStartName + "-" +
//				 location.getLocationDescribe());
//				 Waypoint waypoint = new Waypoint();
//				 waypoint.setLatitude(location.getLatitude());
//				 waypoint.setLongitude(location.getLongitude());
//				 // 过滤点
//				 if (mWayPoints.size() > 0)
//				 {
//				 // 不与起点重复
//				 if (MapUtil.isEqual(waypoint, mWayPoints.get(0)))
//				 {
//				 return;
//				 }
//				 // //去重（有问题）
//				 // if(MapUtil.isEqual(mWayPoints.get(mCounter.getCount() -
//				 // 1), mWayPoints.get(mCounter.getCount() - 2)))
//				 // {
//				 // return;
//				 // }
//				 else
//				 {
//				 mWayPoints.add(waypoint);
//				 mCounter.increase();
//				 }
//				 }

			}
			// 在地图上绘制点、线
			List<Dot> mapDotLst = MapUtil.wayPointsToMapDotLst(getContext(), mWayPoints);
			if (mGraphicMultiPoint != null && mGraphicPolylin != null)
			{
				MapUtil.drawTracksOnMap(getContext(), mMapView, mGraphicMultiPoint, mGraphicPolylin, mapDotLst);
			}
		}
	};

	@Override
	public void onClick(View v)
	{
		switch (v.getId())
		{
		case R.id.title_back:
			mMapActivity.removeFragment(TAG, null);
			mMapActivity.mMapBottomContent.setVisibility(View.VISIBLE);
			mMapActivity.mMapRightContent.setVisibility(View.VISIBLE);
			mMapActivity.mComposerButtonsWrapper.setVisibility(View.VISIBLE);
			mMapActivity.mZoomLayout.setVisibility(View.VISIBLE);
			break;
		case R.id.start_sport_iv:
			startRun();
			break;
		case R.id.stop_sport_iv:

			if (mIsPause)
			{
				mStopImv.setImageResource(R.drawable.pause);
				initLocation();
				locationService.start();
				mIsPause = false;
				mTimeCm.start();
			}
			else
			{
				mStopImv.setImageResource(R.drawable.ico_continue);
				locationService.stop();
				mIsPause = true;
				mTimeCm.stop();
			}
			break;
		case R.id.finish_sport_iv:
			DialogUtil.createTwoButtonDialog(getContext(), "是否保存当前轨迹记录", null, null, null, "确定", "取消", new DialogInterface.OnClickListener()
			{
				@Override
				public void onClick(DialogInterface dialog, int which)
				{
					locationService.stop();
					mTimeCm.stop();
					mEndlongTime = System.currentTimeMillis();

					mCurrentTime = ValueUtil.getCurrentTime();
					saveGPX();
					mMapView.getScreenSnapshot(0, mMapView.getMeasuredHeight() / 4, mMapView.getMeasuredWidth(), (mMapView.getMeasuredHeight() * 3) / 4, screenSnapshotCallback);
					// onDestroyView();
					mMapActivity.removeFragment(TAG, null);
					mMapActivity.mMapBottomContent.setVisibility(View.VISIBLE);
					mMapActivity.mMapRightContent.setVisibility(View.VISIBLE);
					mMapActivity.mComposerButtonsWrapper.setVisibility(View.VISIBLE);
					mMapActivity.mZoomLayout.setVisibility(View.VISIBLE);
				}
			}, null).show();
			break;
		case R.id.more_btn:
			new PopupWindowUtil(new PopupWindowConfirmListener()
			{
				@Override
				public void onPopupWindowConfirm(int state, PopupWindow popupWindow)
				{
					if (state == 0)
					{
						// 显示
						mMapActivity.mMapBottomContent.setVisibility(View.VISIBLE);
						mMapActivity.mMapRightContent.setVisibility(View.VISIBLE);
						mMapActivity.mComposerButtonsWrapper.setVisibility(View.VISIBLE);
						mMapActivity.mZoomLayout.setVisibility(View.VISIBLE);
						popupWindow.dismiss();

						mMapActivity.startActivityForResult(new Intent(getContext(), MyTracksActivity.class), mMapActivity.TracksRequestCode);
						mMapActivity.removeFragment(TAG, null);
					}
					if (state == 1)
					{
						popupWindow.dismiss();
						TracksRecordSettingFrag trackSetting = new TracksRecordSettingFrag();
						mMapActivity.addFragment(EnumViewPos.FULL, trackSetting, trackSetting.getName(), null);
					}

				}
			}).showTracksSettingPopWindow(mMapActivity, mTrackSetting);

			break;

		default:
			break;
		}

	}

	/**
	 * 开始运动轨迹
	 */
	private void startRun()
	{
		checkGpsState();

		if (mStartImv.getVisibility() == View.VISIBLE)
		{
			initLocation();
			locationService.start();// 定位SDK
			mStartImv.setVisibility(View.GONE);
			mTrackSetting.setVisibility(View.GONE);
			mStopImv.setVisibility(View.VISIBLE);
			mFinishImv.setVisibility(View.VISIBLE);
			mRunInfoLayout.setVisibility(View.VISIBLE);
			mTimeCm.setBase(SystemClock.elapsedRealtime());
			mTimeCm.start();
			mStartlongTime = java.lang.System.currentTimeMillis();
		}
	}

	/**
	 * 保存轨迹文件到本地
	 */
	private void saveGPX()
	{
		try
		{
			//简单要素类的形式存储轨迹
			mMapgisTrack.createTrackFeatureCls(TRACKS_PATH + "/track.mgdb|" + mTrack.getName());

			// Track
			String time = ValueUtil.showTimeCount(mEndlongTime - mStartlongTime);
			HashSet<Track> trackSet = new HashSet<Track>();
			mTrack.setTrackPoints(mWayPoints);
			mTrack.setComment(mTrackDis);
			mTrack.setDescription(time);
			trackSet.add(mTrack);
			
			String fileName = TRACKS_PATH + "/" + mCurrentTime + "/" + mTrack.getName() + "-" + mTrack.getComment() + "-" + mTrack.getDescription() + ".gpx";
			File file = new File(fileName);
			if (!file.getParentFile().exists())
			{
				// 创建文件夹
				file.getParentFile().mkdirs();
			}
			GPXParser parser = new GPXParser();
			FileOutputStream out = new FileOutputStream(fileName);
			GPX gpx = new GPX();
			gpx.setVersion("1.0");
			gpx.setCreator("www.smaryun.com");
			gpx.setTracks(trackSet);
			parser.writeGPX(gpx, out);
			// out.flush();
			out.close();
		}
		catch (ParserConfigurationException e)
		{
			e.printStackTrace();
		}
		catch (TransformerException e)
		{
			e.printStackTrace();
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

	}

	/**
	 * 计算运动过程中的距离
	 * 
	 * @param dot1
	 * @param dot2
	 * @return
	 */
	private String getRouteDis(Dot dot1, Dot dot2)
	{
		String strDis = "0.0km";
		double length = MapUtil.dotDistance(PointTransferUtil.Lonlat2Mercator(dot1), PointTransferUtil.Lonlat2Mercator(dot2));
		if (length < 1)
		{
			strDis = "0.1m";
		}
		else if (length < 100)
		{
			DecimalFormat df = new DecimalFormat("###0.00");
			strDis = df.format(length) + "m";
		}
		else
		{
			DecimalFormat df = new DecimalFormat("###0.00");
			strDis = df.format(length / 1000) + "km";
		}

		return strDis;

	}

	/**
	 * 在地图上添加GraphicImage
	 * 
	 * @param bitmap
	 * @param curPoint
	 */
	public void addGraphicImg(Bitmap bitmap, Dot curPoint)
	{
		mGraphicImage.setImage(bitmap);
		mGraphicImage.setPoint(curPoint);
		mGraphicImage.setAnchorPoint(new PointF(0.5f, 0.0f));
		mMapView.getGraphicsOverlay().addGraphic(mGraphicImage);
		mMapView.refresh();
	}

	/**
	 * 检查GPS的状态是否开启
	 */
	public void checkGpsState()
	{
		// 通过系统服务，取得LocationManager对象
		LocationManager locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
		// 判断GPS是否正常启动
		if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
		{
			ToolToast.showShort("请开启GPS导航...");
			// 返回开启GPS导航设置界面
			Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
			startActivityForResult(intent, 0);
			return;
		}
	}

	/**
	 * 截屏监听
	 */
	MapViewScreenSnapshotCallback screenSnapshotCallback = new MapViewScreenSnapshotCallback()
	{

		@Override
		public void onScreenSnapshot(int left, int top, int width, int height, Bitmap bitmap)
		{
			try
			{
				String filePath = TRACKS_PATH + "/" + mCurrentTime + "/" + mTrack.getName() + ".png";
				File file = new File(filePath);
				if (!file.getParentFile().exists())
				{
					file.getParentFile().mkdirs();
				}

				byte[] bytes = BitmapUtils.Bitmap2Bytes(bitmap);
				BitmapUtils.writeBytesFile(bytes, filePath);
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		

		}

		@Override
		public void onScreenSnapshot(Bitmap bitmap)
		{
			
		}
	};

	@Override
	public void onDestroyView()
	{
		// locationService.unregisterListener(mMyLocationListener); // 注销掉监听
		// locationService.stop(); // 停止定位服务
		// 清除Message和Runnable,清除队列中多余的空间
		locHander.removeCallbacks(null);

		mMapView.getGraphicsOverlay().removeGraphic(mGraphicImage);
		mMapView.getGraphicsOverlay().removeGraphic(mGraphicMultiPoint);
		mMapView.getGraphicsOverlay().removeGraphic(mGraphicPolylin);
		mGraphicMultiPoint = null;
		mGraphicPolylin = null;
		// 移除所有GFraphic导致程序崩溃
		// mMapView.getGraphicLayer().removeAllGraphics();
		mMapView.refresh();
//		releaseWakeLock();
		acquireWakeLock();

		super.onDestroyView();
	}

	@Override
	public void onResume()
	{
		getFocus();
		super.onResume();
	}

	/**
	 * 捕捉返回事件 说明：本方式适用于Fragment页面中没有其他可以获取焦点的View（如EditText）
	 */
	private void getFocus()
	{
		getView().setFocusable(true);
		getView().setFocusableInTouchMode(true);
		getView().requestFocus();
		getView().setOnKeyListener(new View.OnKeyListener()
		{

			@Override
			public boolean onKey(View v, int keyCode, KeyEvent event)
			{
				if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK)
				{
					// 监听到返回按钮点击事件

					DialogUtil.createTwoButtonDialog(getContext(), "不保存轨迹记录并退出", null, null, null, "确定", "取消", new DialogInterface.OnClickListener()
					{
						@Override
						public void onClick(DialogInterface dialog, int which)
						{
							mMapActivity.removeFragment(TAG, null);
							mMapActivity.mMapBottomContent.setVisibility(View.VISIBLE);
							mMapActivity.mMapRightContent.setVisibility(View.VISIBLE);
							mMapActivity.mComposerButtonsWrapper.setVisibility(View.VISIBLE);
							mMapActivity.mZoomLayout.setVisibility(View.VISIBLE);
						}
					}, null).show();

//					return false;// 未处理
					return true;
				}
				return false;
			}
		});
	}

	@Override
	public void onSaveInstanceState(Bundle outState)
	{
		Log.e(TAG, "onSaveInstanceState()  run !!!");
		// ToolToast.showShort("onSaveInstanceState() run!!!!");
		// 当Fragmnet销毁保存记录轨迹点
		if (mWayPoints.size() > 0)
		{
//			outState.putParcelableArrayList("mWayPoints", (ArrayList<? extends Parcelable>) mWayPoints);
			 outState.putParcelable("mWayPoints", (Parcelable) mWayPoints);
		}
		super.onSaveInstanceState(outState);
	}

	/**
	 * 获取电源锁，保持该服务在屏幕熄灭时仍然获取CPU时，保持运行
	 */
	private void acquireWakeLock()
	{
		if (null == wakeLock)
		{
			PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
			wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, getClass().getCanonicalName());
			if (null != wakeLock)
			{
				Log.i(TAG, "call acquireWakeLock");
				wakeLock.acquire();
			}
		}
	}

	// 释放设备电源锁
	private void releaseWakeLock()
	{
		if (null != wakeLock && wakeLock.isHeld())
		{
			Log.i(TAG, "call releaseWakeLock");
			wakeLock.release();
			wakeLock = null;
		}
	}

	@Override
	public boolean goback()
	{
		return false;
	}

	@Override
	public boolean isLocked()
	{
		return false;
	}

	@Override
	public String getName()
	{
		return TAG;
	}

}
